package io.cucumber.core.runner;

import com.zws.cucumber.ZwsUtils;
import com.zws.cucumber.util.colorfullog.ZwsColorfulLogger;
import io.cucumber.core.gherkin.Pickle;
import io.cucumber.core.gherkin.Step;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;

public class CoreRunnerTestCaseHelper {

    private static final Logger logger = ZwsColorfulLogger.of(LoggerFactory.getLogger(CoreRunnerTestCaseHelper.class));

//    private static final String SNAPSHOT_BACKGROUND = "background";

//    private static volatile ZwsSnapshotFacade snapshotFacade;

//    private static String skipStepsText;

//    private static ZwsSnapshotFacade getSnapshotFacade() {
//        if (snapshotFacade == null) {
//            synchronized (ZwsSnapshotFacade.class) {
//                if (snapshotFacade == null) {
//                    snapshotFacade = (ZwsSnapshotFacade) ZwsCommonConf.getApplicationContext().getBean("snapshotFacade");
//                }
//            }
//        }
//        return snapshotFacade;
//    }

    /**
     * filter background step
     * @param eventTestCase
     * @return
     * @throws Throwable
     */
    public static io.cucumber.plugin.event.TestCase cloneTestCaseAsDefinition(io.cucumber.plugin.event.TestCase eventTestCase) {
        // skip background step
        Pickle pickle = getFieldValue(eventTestCase, "pickle");
        int scenarioLine = pickle.getScenarioLocation().getLine();
        int skipSteps = 0;
        for (Step step : pickle.getSteps()) {
            // same feature file, and step line is smaller than the scenario
            if (step.getLine() < scenarioLine) {
                logger.warn("skip background step: <b><bold>{}</bold></b>", step.getText());
                skipSteps++;
            }
        }
        // clone test case
        return cloneTestCase(eventTestCase, skipSteps);
    }

    public static io.cucumber.plugin.event.TestCase cloneTestCaseAsInstance(io.cucumber.plugin.event.TestCase testCase) throws Throwable {
        return cloneTestCase(testCase, 0);
    }

    private static io.cucumber.plugin.event.TestCase cloneTestCase(
            io.cucumber.plugin.event.TestCase eventTestCase,
            int skipSteps) {

        TestCase origin = (TestCase) eventTestCase;
        return new TestCase(
                origin.getId(),
                CoreRunnerTestStepHelper.cloneTestSteps(getFieldValue(origin, "testSteps"), skipSteps),
                new ArrayList<>(),
                new ArrayList<>(),
                getFieldValue(eventTestCase, "pickle"),
                false);
    }

    public static void setDryRun(io.cucumber.plugin.event.TestCase eventTestCase) {
        TestCase origin = (TestCase) eventTestCase;
        setFieldValue(origin, "executionMode", ExecutionMode.DRY_RUN);
    }

    public static String getFeaturePath(io.cucumber.plugin.event.TestCase eventTestCase) {
        TestCase testCase = (TestCase) eventTestCase;
        Pickle pickle = getFieldValue(testCase, "pickle");
        return pickle.getUri().toString();
    }

//    public static boolean injectSnapshotTakeStep(io.cucumber.plugin.event.TestCase eventTestCase) {
//
//        TestCase testCase = (TestCase) eventTestCase;
//        int lineOfScenario = getScenarioLine(testCase);
//
//        List<PickleStepTestStep> testSteps = getFieldValue(testCase, "testSteps");
//        StringBuilder sb = new StringBuilder();
//        int idx = 0;
//        for (; idx < testSteps.size(); idx++) {
//            PickleStepTestStep step = testSteps.get(idx);
//            if (step.getStepLine() > lineOfScenario) {
//                break;
//            }
//            sb.append("\t").append(step.getStepText()).append("\n");
//        }
//        if (idx > 0) {
//            logger.debug("add snapshot take step at {}", idx);
////            getSnapshotFacade().deleteSnapshot("test");
//            testSteps.add(0, CoreRunnerTestStepHelper.newSnapshotDeletePickleStepTestStep(CoreRunnerTestCaseHelper::getSnapshotFacade, SNAPSHOT_BACKGROUND));
//            testSteps.add(idx + 1, CoreRunnerTestStepHelper.newSnapshotTakePickleStepTestStep(CoreRunnerTestCaseHelper::getSnapshotFacade, SNAPSHOT_BACKGROUND));
//            skipStepsText = sb.toString();
//            return true;
//        }
//        return false;
//    }
//
//    public static void skipBackgroundStepAndInjectSnapshotRestoreStep(io.cucumber.plugin.event.TestCase eventTestCase) {
//        TestCase testCase = (TestCase) eventTestCase;
//        int lineOfScenario = getScenarioLine(testCase);
//
//        List<PickleStepTestStep> testSteps = getFieldValue(testCase, "testSteps");
//        int originalSize = testSteps.size();
//        Iterator<PickleStepTestStep> itor = testSteps.iterator();
//        while (itor.hasNext()) {
//            PickleStepTestStep step = itor.next();
//            if (step.getStepLine() < lineOfScenario) {
//                itor.remove();
//            } else {
//                break;
//            }
//        }
//        logger.debug("skip background step size: {}", originalSize - testSteps.size());
//        testSteps.add(0, CoreRunnerTestStepHelper.newSnapshotRestorePickleStepTestStep(CoreRunnerTestCaseHelper::getSnapshotFacade, SNAPSHOT_BACKGROUND, skipStepsText));
//    }

//    private static int getScenarioLine(TestCase testCase) {
//        return CoreGherkinMessagePickleHelper.getScenarioLine(getFieldValue(testCase, "pickle"));
//    }

    private static <T> T getFieldValue(Object object, String fieldName) {
        return ZwsUtils.getFieldValue(TestCase.class, fieldName, object);
    }

    private static void setFieldValue(Object object, String fieldName, Object value) {
        ZwsUtils.setFieldValue(TestCase.class, fieldName, object, value);
    }

}
